package cn.iune.config;

import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import cn.iune.web.security.shiro.ChainDefinitionSectionMetaSource;
import cn.iune.web.security.shiro.MyFormAuthenticationFilter;
import cn.iune.web.security.shiro.MyPermissionsAuthorizationFilter;
import cn.iune.web.security.shiro.MyRolesAuthorizationFilter;
import cn.iune.web.security.shiro.MyShiroSessionListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.config.Ini.Section;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;


//@DependsOn("entityManagerFactory")
//@DependsOn("jpaContext")
//@Order(2000)
//@AutoConfigureAfter(DruidDataSourceConfig.class)//配置Bean加载的先后顺序
//@EnableAutoConfiguration
@Configuration
//@AutoConfigureAfter(ShiroLifecycleBeanPostProcessorConfig.class)//配置Bean加载的先后顺序
public class ShiroConfig {
	
	public ShiroConfig() {
		System.out.println("应用程序启动！ShiroConfig.class配置BEAN");
	}

	
	/**
     * Shiro生命周期处理器
     *
     * @return
     */
	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		System.out.println("-----SpringbootShiroConfig-----lifecycleBeanPostProcessor");
		return new LifecycleBeanPostProcessor();
	}
	
	
	//开启shiro aop注解支持, 启用认证注解
	@Bean("defaultAdvisorAutoProxyCreator")
//	@ConditionalOnMissingBean
//	@DependsOn("lifecycleBeanPostProcessor")
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		System.out.println("-----SpringbootShiroConfig-----defaultAdvisorAutoProxyCreator");
		DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
		return defaultAdvisorAutoProxyCreator;
	}
	
	//开启shiro aop注解支持, 启用权限注解
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") org.apache.shiro.mgt.SecurityManager securityManager)
    {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
    
    
    
	@Bean("myRealm1")
	public MyRealm myRealm() {
		System.out.println("-----SpringbootShiroConfig-----myRealm");
		return new MyRealm();
	}

	@Bean("sessionIdCookie")
	public SimpleCookie sessionIdCookie() {
		System.out.println("-----SpringbootShiroConfig-----sessionIdCookie");
		SimpleCookie sessionIdCookie = new SimpleCookie();
		sessionIdCookie.setName("sid");
		sessionIdCookie.setHttpOnly(true);
		sessionIdCookie.setMaxAge(-1);
		return sessionIdCookie;
	}
	
	@Bean("sessionIdGenerator")
	public JavaUuidSessionIdGenerator sessionIdGenerator() {
		System.out.println("-----SpringbootShiroConfig-----sessionIdGenerator");
		return new JavaUuidSessionIdGenerator();
	}
	
	@Bean("sessionDAO")
	public EnterpriseCacheSessionDAO sessionDAO(JavaUuidSessionIdGenerator sessionIdGenerator) {
		System.out.println("-----SpringbootShiroConfig-----sessionDAO");
		EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
		sessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache-miduo");
		sessionDAO.setSessionIdGenerator(sessionIdGenerator);
		return sessionDAO;
	}
	
	@Bean("cacheManager")
	public EhCacheManager cacheManager() {
		System.out.println("-----SpringbootShiroConfig-----cacheManager");
		return new EhCacheManager();
	}
	
//	@Bean(name = "shiroEhcacheManager") 
//	public EhCacheManager getEhCacheManager() { 
//		EhCacheManager em = new EhCacheManager(); 
//		em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); 
//		return em; 
//	}
	
	
	@Bean("sessionManager")
	public DefaultWebSessionManager sessionManager(EnterpriseCacheSessionDAO sessionDAO, SimpleCookie sessionIdCookie) {
		System.out.println("-----SpringbootShiroConfig-----sessionManager");
		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setGlobalSessionTimeout(1800000);
		
//		sessionManager.setDeleteInvalidSessions(true);
//		sessionManager.setSessionValidationSchedulerEnabled(true);
//		sessionManager.setSessionValidationScheduler(sessionValidationScheduler());
		
		sessionManager.setSessionIdCookieEnabled(true);
		sessionManager.setSessionIdCookie(sessionIdCookie);
		
		sessionManager.setSessionDAO(sessionDAO);
		
		Collection<SessionListener> listeners = new ArrayList<SessionListener>();
		listeners.add(new MyShiroSessionListener());
		sessionManager.setSessionListeners(listeners);
		
		return sessionManager;
	}
	
	@Bean("sessionValidationScheduler")
	public QuartzSessionValidationScheduler sessionValidationScheduler(ValidatingSessionManager sessionManager) {
		System.out.println("-----SpringbootShiroConfig-----sessionValidationScheduler");
		QuartzSessionValidationScheduler sessionValidationScheduler = new QuartzSessionValidationScheduler();
		sessionValidationScheduler.setSessionValidationInterval(1800000);
		sessionValidationScheduler.setSessionManager(sessionManager);
		return sessionValidationScheduler;
	}
	
	@Bean("rememberMeCookie")
	public SimpleCookie rememberMeCookie() {
		System.out.println("-----SpringbootShiroConfig-----rememberMeCookie");
		SimpleCookie rememberMeCookie = new SimpleCookie();
		rememberMeCookie.setName("rememberMe");
		rememberMeCookie.setHttpOnly(true);
		rememberMeCookie.setMaxAge(31104000);//360天
		return rememberMeCookie;
	}
	
	@Bean("rememberMeManager")
	public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) {
		System.out.println("-----SpringbootShiroConfig-----rememberMeManager");
		CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
		byte[] cipherKey = Base64.decode("4AvVhmFLUs0KTA3Kprsdag==");//"#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}";
		rememberMeManager.setCipherKey(cipherKey);
		rememberMeManager.setCookie(rememberMeCookie);
		return rememberMeManager;
	}
	
	//<!-- 配置权限管理器 -->  
	@Bean("securityManager")
	public DefaultWebSecurityManager securityManager(Realm myRealm) {
		System.out.println("-----SpringbootShiroConfig-----securityManager");
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myRealm);
		securityManager.setCacheManager(cacheManager());
//		securityManager.setSessionManager(sessionManager());
//		securityManager.setRememberMeManager(rememberMeManager());
		return securityManager;
	}
	
//  web应用管理配置
//	@Bean
//	public DefaultWebSecurityManager securityManager(Realm shiroRealm, CacheManager cacheManager, RememberMeManager manager) {
//		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//		securityManager.setCacheManager(cacheManager);
//		securityManager.setRememberMeManager(manager);//记住Cookie
//		securityManager.setRealm(shiroRealm);
//		return securityManager;
//	}
	
	@Bean("chainDefinitionSectionMetaSource")
	public ChainDefinitionSectionMetaSource chainDefinitionSectionMetaSource() {
		System.out.println("-----SpringbootShiroConfig-----chainDefinitionSectionMetaSource");
		ChainDefinitionSectionMetaSource chainDefinitionSectionMetaSource = new ChainDefinitionSectionMetaSource();
		String filterChainDefinitions = "/favicon.ico = anon";
		chainDefinitionSectionMetaSource.setFilterChainDefinitions(filterChainDefinitions);
		return chainDefinitionSectionMetaSource;
	}


    
	@Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
		System.out.println("-----SpringbootShiroConfig-----shiroFilter");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/blogin");
        shiroFilterFactoryBean.setSuccessUrl("/admin");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        
        Map<String,Filter> filters = new HashMap<String,Filter>();
        filters.put("authc", new MyFormAuthenticationFilter());
        filters.put("roles", new MyRolesAuthorizationFilter());
        filters.put("perms", new MyPermissionsAuthorizationFilter());
        
        shiroFilterFactoryBean.setFilters(filters);
        
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/favicon.ico", "anon");
        filterChainDefinitionMap.put("/admin/lib/**", "anon");
        filterChainDefinitionMap.put("/admin/js/**", "anon");
        filterChainDefinitionMap.put("/admin/css/**", "anon");
        filterChainDefinitionMap.put("/admin/authen/**", "anon");
        
        filterChainDefinitionMap.put("/appcenter/frame", "authc");

        filterChainDefinitionMap.put("/inventory/**", "authc");
        
        filterChainDefinitionMap.put("/hello/**", "authc");
        filterChainDefinitionMap.put("/admin/**", "authc");
        
        
		filterChainDefinitionMap.put("/clip-two/Html-Admin/**", "anon");
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/user", "roles[user]");
		filterChainDefinitionMap.put("/admin", "roles[admin]");
//		filterChainDefinitionMap.put("/**", "user");//user允许 记住我和授权用户 访问，但在进行下单和支付时建议使用authc

//        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
      
		Section section = chainDefinitionSectionMetaSource().getObject();
		section.putAll(filterChainDefinitionMap);
		shiroFilterFactoryBean.setFilterChainDefinitionMap(section);
        
        
        return shiroFilterFactoryBean;

	}


	/** 
     * FilterRegistrationBean 
     * @return 
     */  
//    @Bean  
    public FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean() {  
		System.out.println("-----SpringbootShiroConfig-----shiroFilter------FilterRegistrationBean");
        FilterRegistrationBean<DelegatingFilterProxy> filterRegistration = new FilterRegistrationBean<DelegatingFilterProxy>();  
        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));   
        filterRegistration.setEnabled(true);  
        filterRegistration.addUrlPatterns("/");   
        filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);  
        return filterRegistration;  
    }  	


	
	
	

}
